package com.hengxin.shiro;

import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.hengxin.bean.ShiroUserm;
import com.hengxin.constant.StateConstant;
import com.hengxin.module.common.entity.Userm;
import com.hengxin.module.common.service.UsermService;
import com.hengxin.module.common.web.KaptchaController;
import com.hengxin.module.setting.service.MenuService;
import com.hengxin.module.setting.service.RoleService;
import com.hengxin.module.setting.service.UsermOrganizationService;
import com.hengxin.shiro.bean.CaptchaUsernamePasswordToken;
import com.hengxin.shiro.exception.CaptchaException;

public class ShiroServiceRealm extends AuthorizingRealm {

	
	//private PasswordService passwordService;
	private UsermService usermService;
	
	private RoleService roleService;
	
	private MenuService menuService;
	
	private UsermOrganizationService usermOrganizationService;
	



	public ShiroServiceRealm(){
	}
	
	
	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.登陆之后会被调用的
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {		//principalCollection 身份集合，从身份集合中获取相应的权限集合
		
		System.out.println("principalCollection....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
		ShiroUserm shiroUserm = (ShiroUserm)principalCollection.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		
		Set<String> roles = roleService.findByIdentifier(shiroUserm.getOrganId(), shiroUserm.getId());
		authorizationInfo.setRoles(roles);
		
		Set<String> menus = menuService.findMenuPermission(shiroUserm.getOrganId(), shiroUserm.getId());
		authorizationInfo.setStringPermissions(menus);
		//TODO  暂时不支持组织型的菜单控制
		return authorizationInfo;
	}

	
	
	/**
	 * 认证回调函数,登录时调用   subject.login(token);调用该方法时调用
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authenticationToken) throws AuthenticationException {
		CaptchaUsernamePasswordToken  token  = (CaptchaUsernamePasswordToken) authenticationToken;
		
		Session seesion = SecurityUtils.getSubject().getSession();
		String kaptcha = (String)seesion.getAttribute(KaptchaController.KAPTCHA);
		if( !kaptcha.equalsIgnoreCase(token.getCaptcha())){
			throw new CaptchaException();					//验证码错误
		}			
		
		Userm userm = usermService.findByAccount(token.getUsername());
		if(userm == null){
			throw new UnknownAccountException();			//没有该账号
		}else if(StateConstant.USERM_STATE_FROZEN.equals(userm.getUserState())){	
			throw new LockedAccountException();				//账号被冻结
		}
		ShiroUserm shiroUserm = new ShiroUserm(userm);
		List<Long> organIds = usermOrganizationService.findOrganIdByUsermId(shiroUserm.getId());
		if(CollectionUtils.isNotEmpty(organIds)){
			shiroUserm.setOrganId(organIds.get(0));
		}
		return new SimpleAuthenticationInfo(shiroUserm, userm.getPwd(),ByteSource.Util.bytes(userm.getSalt()), userm.getName());
	}

	
	/**
	 * @param usermOrganizationService the usermOrganizationService to set
	 */
	public void setUsermOrganizationService(
			UsermOrganizationService usermOrganizationService) {
		this.usermOrganizationService = usermOrganizationService;
	}

	/**
	 * @param usermService the usermService to set
	 */
	public void setUsermService(UsermService usermService) {
		this.usermService = usermService;
	}
	
	/**
	 * @param roleService the roleService to set
	 */
	@Autowired
	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}


	/**
	 * @param menuService the menuService to set
	 */
	@Autowired
	public void setMenuService(MenuService menuService) {
		this.menuService = menuService;
	}
	
	
	
	
}
